<html>
<head>
<title>CpcPaChi - Version 0.12</title>
<style type="text/css">
span {
    font-family: 'Courier New';
    font-size: 10pt;
    color: #000000;
}
.sc0 {
    color: #808080;
}
.sc3 {
    color: #008080;
}
.sc4 {
    color: #FF8000;
}
.sc5 {
    font-weight: bold;
    color: #0000FF;
}
.sc7 {
    color: #808080;
}
.sc9 {
    color: #804000;
}
.sc10 {
    font-weight: bold;
    color: #000080;
}
.sc11 {
}
</style>
</head>
<body>
<h2>Un compilador sencillo paso a paso (12 - Condiciones simples)</h2>

<p align="right">(Volver al <a href="doc.html">&iacute;ndice</a>) </p>

<p>Ahora que sabemos hacer saltos, podemos hacer comprobaciones del
tipo if..then..else</p>

<p>La idea es que un bloque como</p>

<pre><code>if condicion then
  begin
  bloque1
  end
else
  begin
  bloque2
  end
restoDePrograma</code></pre>

<p>Se podr&iacute;a reescribir como</p>

<pre><code>if not condicion then goto inicioBloque2;
  begin
  bloque1
  goto inicioRestoDePrograma;
  end;
inicioBloque2
  begin
  bloque2
  end
inicioRestoDePrograma:
  restoDePrograma</code></pre>

<p>Y esa construcci&oacute;n ya tiene una traducci&oacute;n
casi directa a ensamblador (y, por tanto, a c&oacute;digo
m&aacute;quina).</p>


<p><br />En cuanto a las condiciones, nos centraremos por ahora
en condiciones muy sencillas, del estilo de "if x > 2 then ...".</p>

<p>La forma en que lo haremos en c&oacute;digo m&aacute;quina de Z80
ser&aacute; la siguiente:
</p>

<ul>
  <li>El primer valor a comparar lo guardaremos en el registro A.</li>
  <li>El segundo valor lo guardaremos en el registro B.</li>
  <li>Compararemos los valores guardados en ambos registros, usando la
    orden CP (que realmente hace una resta entre ambos valores).</li>
  <li>Usaremos el "flag" adecuado para cada tipo de comparaci&oacute;n:
    para &quot;if a = b&quot; usar&iacute;amos &quot;JP Z&quot; (saltar
      si se activa el flag Z     porque el resultado de la &uacute;ltima
      operaci&oacute;n sea cero);
    para &quot;if a &lt; b &quot; usar&iacute;amos &quot;JP C&quot;
      (saltar si se activa el flag C     porque haya habido
      &quot;acarreo&quot; en el resultado de la &uacute;ltima
      operaci&oacute;n -valor negativo-) o bien &quot;JP M&quot;
      (saltar si  resultado negativo);
    para &quot;if a &gt; b&quot; usar&iacute;amos &quot;JP P&quot;
      (saltar si resultado positivo).
    </li>
</ul>

<p>Esto se convertir&iacute;a en algo como</p>

<pre><code>
/* Generar codigo para comparacion IF  */
public void genIF(string ident1, char tipoComparacion,
  string ident2)
{
  // Primero guardo ident2 en B
  ficheroDestino.WriteLine(lineaActual+&quot;' IF &quot;+ident1
    + tipoComparacion + ident2 );
  lineaActual += 10;
  GenLecturaValor(ident2);
  ficheroDestino.WriteLine(lineaActual+&quot; DATA 47:' LD B, A (&quot;+ident2+&quot;)&quot; );
  lineaActual += 10;
  longitudTotal ++;

  // Luego guardo ident1 en A
  GenLecturaValor(ident1);

  // Ahora preparo la comparacion
  ficheroDestino.WriteLine(lineaActual + &quot; DATA B8:' CP B&quot; );
  lineaActual += 10;
  if (tipoComparacion == '=')
    ficheroDestino.WriteLine(lineaActual + &quot; DATA C2:' JP NZ&quot; );
  else if (tipoComparacion == '&gt;')
    ficheroDestino.WriteLine(lineaActual + &quot; DATA FA:' JP M&quot; );
  else if (tipoComparacion == '&lt;')
    ficheroDestino.WriteLine(lineaActual + &quot; DATA F2:' JP P&quot; );
  else
    miLexer.ErrorFatal(&quot;Comparacion incorrecta&quot;);
  lineaActual += 10;
  longitudTotal += 2;
  necesariaSegundaPasada = true;
}
</code></pre>

<p>(Comparamos con la secuencia inversa, porque queremos ver si se cumple "if not condicion")</p>

<p>Por supuesto, el analizador sint&aacute;ctico tambi&eacute;n tendr&aacute; cambios equivalentes. Por ejemplo, tiene que poder reconocer secuencias IF...THEN...ELSE:</p>

<pre><code>
void analizarIF()
{
  string ident1, ident2, ordenThen, ordenElse;
  char tipoComparacion, terminador;
  string ifActual;

  /* Uso el numero de IF actual para generar
     las etiquetas de salto. Lo copio en una variable
     local para evitar modificaciones inesperadas
     en IF anidados */
  ifActual = Convert.ToString(numeroIFactual);
  miTablaSimb.Insertar(&quot;ELSE_&quot;+ifActual, tipoId.LABEL,
    tamDato.INTEGER, 0 );
  miTablaSimb.Insertar(&quot;FIN_IF_&quot;+ifActual, tipoId.LABEL,
    tamDato.INTEGER, 0 );
  // Comienza el analisis en si
  ident1 = miLexer.ObtenerIdentificador().ToUpper();
  tipoComparacion = miLexer.LeerCualquierSimbolo();
  ident2 = miLexer.ObtenerEnteroOIdentificador().ToUpper();
  ordenThen = miLexer.ObtenerIdentificador().ToUpper();
  if (ordenThen != &quot;THEN&quot;) miLexer.ErrorFatal(&quot;IF sin THEN&quot;);
  miGenerador.genIF(ident1, tipoComparacion, ident2);
  miGenerador.genDireccSinGOTO(&quot;ELSE_&quot;+ifActual);
  // Bloque de codigo tras IF-THEN  (ELSE o otra orden)
  analizarBloqueBEGIN_END();
  miGenerador.genGOTO(&quot;FIN_IF_&quot;+ifActual);
  miGenerador.genLABEL(&quot;ELSE_&quot;+ifActual);
  ordenElse = miLexer.ObtenerIdentificador().ToUpper();
  if (ordenElse == &quot;ELSE&quot;)
    {
    analizarBloqueBEGIN_END();
    terminador = miLexer.LeerCualquierSimbolo();
    }
  else
  {
    string orden = miLexer.ObtenerIdentificador().ToUpper();
    analizarCualquierOrden( orden );
  }
  /* Si no, es ; o error */
  /*if terminador &lt;&gt; ';' then
    errorFatal('Sin ; al final de IF');*/
  miGenerador.genLABEL(&quot;FIN_IF_&quot;+ifActual);
}
</code></pre>


<p>Tambi&eacute;n es necesario alg&uacute;n otro cambio peque&ntilde;o en el fuente,
para permitir bloques begin...end, pero eso es muy
sencillo...
</p>

<p><br>
  Como siempre, para m&aacute;s detalles, todo el c&oacute;digo est&aacute; en la p&aacute;gina del proyecto en Google Code:<br />
  <br />
  <a href="http://code.google.com/p/cpcpachi/">http://code.google.com/p/cpcpachi/</a></p>
<p align="right">(Volver al <a href="doc.html">&iacute;ndice</a>) </p>
</body>
</html>
